﻿using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace Common.Helpers
{
    public class ClickUtil
    {

        private static DateTime _lastInvokeTime;
        private static DateTime _lastClickTime;
        private static readonly object _lock = new object();
        private static CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();

        public static Dictionary<int, DateTime> ThrottleMap = new Dictionary<int, DateTime>();

        /// <summary>  
        /// 节流方法，确保在指定的时间间隔内只执行一次事件处理逻辑。  
        /// </summary>  
        /// <param name="action">要执行的事件处理逻辑。</param>  
        /// <param name="throttleTime">节流时间间隔（毫秒）。</param>  
        public static void Throttle(Action action, int throttleTime)
        {
            lock (_lock)
            {
                // 获取当前时间  
                var now = DateTime.Now;
                var code = action.GetHashCode();

                if (ThrottleMap.TryGetValue(code, out DateTime lastClick))
                {
                    // 判断上次执行时间与当前时间的差值是否大于节流时间  
                    if ((now - lastClick).TotalMilliseconds >= throttleTime)
                    {
                        lastClick = now; // 更新上次执行时间  

                        ThrottleMap[code] = now;

                        action(); // 执行传入的操作  
                    }
                }
                else
                {
                    ThrottleMap.Add(code, now);
                    action(); // 执行传入的操作  
                }
            }
        }


        /// <summary>  
        /// 防抖方法，确保在指定的时间间隔内只执行最后一次事件处理逻辑。  
        /// </summary>  
        /// <param name="action">要执行的事件处理逻辑。</param>  
        /// <param name="wait">等待时间（毫秒）。</param>  
        public static void Debounce(Action action, int wait)
        {
            lock (_lock)
            {
                // 取消上一个任务（如果有的话）  
                _cancellationTokenSource.Cancel();
                _cancellationTokenSource = new CancellationTokenSource(); // 创建新的 CancellationTokenSource  

                // 更新上次调用时间  
                _lastInvokeTime = DateTime.Now;

                // 创建新的任务  
                Task.Run(async () =>
                {
                    try
                    {
                        await Task.Delay(wait, _cancellationTokenSource.Token);

                        // 检查是否在等待期间有新的调用  
                        if ((DateTime.Now - _lastInvokeTime).TotalMilliseconds >= wait)
                        {
                            action(); // 执行传入的操作  
                        }
                    }
                    catch (TaskCanceledException)
                    {
                        // 任务被取消，什么都不做  
                    }
                });
            }
        }
    }
}
